package test;

import com.sun.deploy.panel.ITreeNode;
import com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 描述：
 *       LinkedHashMap底层就是用的HashMap加双链表实现的，而且本身已经实现了按照访问顺序的存储。此外，
 *       LinkedHashMap中本身就实现了一个方法removeEldestEntry用于判断是否需要移除最不常读取的数，
 *       方法默认是直接返回false，不会移除元素，所以需要重写该方法。即当缓存满后就移除最不常用的数。
 * @author hl
 * @version 1.0
 * @date 2020/10/30 10:25
 */
public class LRU <K,V>{
    private static final float hashLoadFactory  = 0.75f;//相当于负载因子，决定开始清除缓存的时机
    private LinkedHashMap<K,V> map;
    private int cacheSize;

    public LRU(int cacheSize) {
        this.cacheSize = cacheSize;
        //将LinkedHashMap的大小设置的比cacheSize大一些，这样做的目的是在面对突发流量的时候留有一定的缓存空间
        int capacity = (int) (Math.ceil(this.cacheSize / hashLoadFactory) + 1);
        map = new LinkedHashMap<K,V>(capacity, hashLoadFactory, true){
            private static final long serialVersionUID = 1;

            @Override
            protected boolean removeEldestEntry(Map.Entry eldest) {
                return size() > LRU.this.cacheSize;
            }
        };
    }

    public synchronized V get(K key) {
        return map.get(key);
    }

    public synchronized void put(K key, V value) {
        map.put(key, value);
    }

    public synchronized void clear() {
        map.clear();
    }

    public synchronized int usedSize() {
        return map.size();
    }

    public void print() {
        for (Map.Entry<K, V> entry : map.entrySet()) {
            System.out.print(entry.getValue() + "--");
        }
        System.out.println();
    }
}
